/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	_SYS_SOCKFILTER_H
#define	_SYS_SOCKFILTER_H

#include <sys/cred.h>
#include <sys/errno.h>
#include <sys/socket.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Opaque socket filter handle
 */
typedef struct __sof_handle	*sof_handle_t;

/*
 * Return values for callback functions.
 *
 * A - Attach (passive/active) only
 * P - Passive attach only
 */
typedef enum {
	SOF_RVAL_DEFER = -3,		/* defer notification (P) */
	SOF_RVAL_DETACH = -2,		/* detach filter, continue proc. (A) */
	SOF_RVAL_CONTINUE = -1,		/* continue processing */
	SOF_RVAL_RETURN = 0,		/* stop proc, does not return error */
	SOF_RVAL_EINVAL = EINVAL,	/* stop proc., returns error */
	SOF_RVAL_EACCES = EACCES,	/* stop proc., returns error */
	SOF_RVAL_ENOMEM = ENOMEM,	/* stop proc., returns error */
	SOF_RVAL_ECONNABORTED = ECONNABORTED /* stop proc, returns error */
} sof_rval_t;

/*
 * Events generated by the sofop_notify callback.
 */
typedef enum {				/* socket ... */
	SOF_EV_CLOSING,			/* ... is closing */
	SOF_EV_CONNECTED,		/* ... is connected */
	SOF_EV_CONNECTFAILED,		/* ... failed to connect */
	SOF_EV_DISCONNECTED,		/* ... was disconnected */
	SOF_EV_CANTRECVMORE,		/* ... cannot receive any more data */
	SOF_EV_CANTSENDMORE,		/* ... cannot send any more data */
	SOF_EV_INJECT_DATA_IN_OK,	/* ... has cleared rcv flow ctrl */
	SOF_EV_INJECT_DATA_OUT_OK,	/* ... has cleared snd flow ctrl */
} sof_event_t;

/* Filter callbacks */
typedef sof_rval_t 	(*sof_attach_active_fn_t)(sof_handle_t, int, int, int,
    cred_t *, void **);
typedef sof_rval_t 	(*sof_attach_passive_fn_t)(sof_handle_t, sof_handle_t,
    void *, struct sockaddr *, socklen_t, struct sockaddr *, socklen_t,
    void **);
typedef void 		(*sof_detach_fn_t)(sof_handle_t, void *, cred_t *);
typedef mblk_t 		*(*sof_data_in_fn_t)(sof_handle_t, void *, mblk_t *,
    int, size_t *);
typedef mblk_t		*(*sof_data_in_proc_fn_t)(sof_handle_t, void *,
    mblk_t *, cred_t *, size_t *);
typedef mblk_t		*(*sof_data_out_fn_t)(sof_handle_t, void *, mblk_t *,
    struct nmsghdr *, cred_t *, sof_rval_t *);
typedef sof_rval_t	(*sof_bind_fn_t)(sof_handle_t, void *,
    struct sockaddr *, socklen_t *, cred_t *);
typedef sof_rval_t	(*sof_listen_fn_t)(sof_handle_t, void *, int *,
    cred_t *);
typedef sof_rval_t	(*sof_accept_fn_t)(sof_handle_t, void *, cred_t *);
typedef sof_rval_t	(*sof_connect_fn_t)(sof_handle_t, void *,
    struct sockaddr *, socklen_t *, cred_t *);
typedef sof_rval_t	(*sof_shutdown_fn_t)(sof_handle_t, void *, int *,
    cred_t *);
typedef sof_rval_t	(*sof_getsockname_fn_t)(sof_handle_t, void *,
    struct sockaddr *, socklen_t *, cred_t *);
typedef sof_rval_t	(*sof_getpeername_fn_t)(sof_handle_t, void *,
    struct sockaddr *, socklen_t *, cred_t *);
typedef sof_rval_t 		(*sof_setsockopt_fn_t)(sof_handle_t, void *,
    int, int, void *, socklen_t *, cred_t *);
typedef sof_rval_t	(*sof_getsockopt_fn_t)(sof_handle_t, void *,
    int, int, void *, socklen_t *, cred_t *);
typedef sof_rval_t	(*sof_ioctl_fn_t)(sof_handle_t, void *, int, intptr_t,
    int, int32_t *, cred_t *);
typedef void		(*sof_mblk_prop_fn_t)(sof_handle_t, void *, ssize_t *,
    ushort_t *, ushort_t *);
typedef void		(*sof_notify_fn_t)(sof_handle_t, void *, sof_event_t,
    uintptr_t);

typedef struct sof_ops {
	sof_attach_active_fn_t	sofop_attach_active;
	sof_attach_passive_fn_t	sofop_attach_passive;
	sof_detach_fn_t		sofop_detach;
	sof_data_in_fn_t	sofop_data_in;
	sof_data_in_proc_fn_t	sofop_data_in_proc;
	sof_data_out_fn_t	sofop_data_out;
	sof_bind_fn_t		sofop_bind;
	sof_listen_fn_t		sofop_listen;
	sof_connect_fn_t	sofop_connect;
	sof_accept_fn_t		sofop_accept;
	sof_shutdown_fn_t	sofop_shutdown;
	sof_getsockname_fn_t	sofop_getsockname;
	sof_getpeername_fn_t	sofop_getpeername;
	sof_setsockopt_fn_t	sofop_setsockopt;
	sof_getsockopt_fn_t	sofop_getsockopt;
	sof_ioctl_fn_t		sofop_ioctl;
	sof_mblk_prop_fn_t	sofop_mblk_prop;
	sof_notify_fn_t		sofop_notify;
} sof_ops_t;

#define	SOF_VERSION	1

extern int	sof_register(int, const char *, const sof_ops_t *, int);
extern int	sof_unregister(const char *);

extern void	sof_newconn_ready(sof_handle_t);
extern void	sof_bypass(sof_handle_t);
extern void	*sof_get_cookie(sof_handle_t);
extern void 	*sof_cas_cookie(sof_handle_t, void *, void *);
extern int	sof_inject_data_out(sof_handle_t, mblk_t *, struct nmsghdr *,
    boolean_t *);
extern int	sof_inject_data_in(sof_handle_t, mblk_t *, size_t, int,
    boolean_t *);
extern void 	sof_rcv_flowctrl(sof_handle_t, boolean_t);
extern void 	sof_snd_flowctrl(sof_handle_t, boolean_t);
extern boolean_t sof_newconn_move(sof_handle_t, sof_handle_t);

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SOCKFILTER_H */
